#ifndef ZL_COLLECTION_DICTIONARY
#define ZL_COLLECTION_DICTIONARY

#include "Interfaces.h"

namespace zl
{
	namespace collections
	{
		template<typename KT, typename VT,
			typename KK = typename KeyType<KT>::Type,
			typename VK = typename KeyType<VT>::Type>
		class Dictionary :public Object
		{
			typedef  SortedList<KT, KK>          KeyContainer;
			typedef  List<VT, VK>                ValueContainer;
		public:
			typedef PairIterator<KT, VT>         iterator;
		protected:
			KeyContainer                         keys_;
			ValueContainer                       values_;
			PairIterator<KT, VT>                 _begin;
			PairIterator<KT, VT>                 _end;
		public:
			Dictionary()
			{

			}

			Dictionary(const iterator& __begin,const iterator& __end):
				keys_(__begin.obj1(),__end.obj1()),
				values_(__begin.obj2(),__end.obj2())
			{

			}

			PairIterator<KT, VT>                   begin()const
			{
				return _begin;
			}

			PairIterator<KT, VT>                    end()const
			{
				return _end;
			}

			const KeyContainer& keys()const
			{
				return keys_;
			}

			const ValueContainer& values()const
			{
				return values_;
			}

			zint size()const
			{
				return keys_.size();
			}

			VT& get(const KK& key)const
			{
				return values_.get(keys_.firstindexof(key));
			}

			VT& operator[](const KK& key)const
			{
				return values_.get(keys_.firstindexof(key));
			}

			bool set(const KK& key, const VT& value)
			{
				zint index = keys_.firstindexof(key);
				if (index == -1)
				{
					index = keys_.add(key);
					values_.insert(index, value);
					_begin = PairIterator<KT, VT>(keys_.begin(), values_.begin());
					_end = PairIterator<KT, VT>(keys_.end(), values_.end());
				}
				else
					values_[index] = value;
				return true;
			}

			bool add(const KT& key, const VT& value)
			{
				assert(!keys_.contains(key));
				zint index = keys_.add(key);
				values_.insert(index, value);
				_begin = PairIterator<KT, VT>(keys_.begin(),values_.begin());
				_end = PairIterator<KT, VT>(keys_.end(),values_.end());
				return true;
			}

			bool remove(const KK& key)
			{
				zint index = keys_.firstindexof(key);
				if (index != -1)
				{
					keys_.removeat(index);
					values_.removeat(index);
					_begin = PairIterator<KT, VT>(keys_.begin(), values_.begin());
					_end = PairIterator<KT, VT>(keys_.end(), values_.end());
					return true;
				}
				else return false;
			}

			Dictionary<KT, VT>&             operator=(const Dictionary<KT,VT>& _right)
			{
				keys_.clear();
				values_.clear();
				keys_ = _right.keys_;
				values_ = _right.values_;
				return *this;
			}

			bool clear()
			{
				keys_.clear();
				values_.clear();
				_begin = PairIterator<KT,VT>(nullptr,nullptr);
				_end = PairIterator<KT,VT>(nullptr,nullptr);
				return true;
			}
		};

		template<typename KT,
			typename VT,
			typename KK = typename KeyType<KT>::Type,
			typename VK = typename KeyType<VT>::Type>

		class Group :public Object
		{
			typedef  SortedList<KT, KK>           KeyContainer;
			typedef  List<VT, VK>                 ValueContainer;
		public:
			typedef  PairIterator<KT, VT>         iterator;
		protected:
			KeyContainer                          keys_;
			List<ValueContainer*>                 values_;
			PairIterator<KT, VT>                  _begin;
			PairIterator<KT, VT>                  _end;
		public:
			Group()
			{

			}

			~Group()
			{
				clear();
			}

			iterator   begin()const
			{
				return _begin;
			}
			
			iterator   end()const
			{
				return _end;
			}

			const KeyContainer& keys()const
			{
				return keys_;
			}

			zint  size()const
			{
				return keys_.size();
			}

			const ValueContainer& get(const KK& key)const
			{
				return *values_.get(keys_.firstindexof(key));
			}

			const ValueContainer& getbyindex(zint index)const
			{
				return *values_.get(index);
			}

			const ValueContainer& operator[](const KK& key)const
			{
				return *values_.get(keys_.firstindexof(key));
			}

			bool contains(const KK& key)const
			{
				return keys_.contains(key);
			}

			bool contains(const KK& key, const VK& value)const
			{
				zint index = keys_.firstindexof(key);
				if (index != -1)
				{
					return values_.get(index)->contains(value);
				}
				else return false;
			}

			bool add(const Pair<KT, VT>& value)
			{
				return add(value.key, value.value);
			}

			bool add(const KT& key, const VT& value)
			{
				ValueContainer* target = 0;
				zint index = keys_.firstindexof(key);
				if (index == -1)
				{
					target = new ValueContainer;
					values_.insert(keys_.add(key), target);
				}
				else
				{
					target = values_[index];
				}
				target->add(value);
				return true;
			}

			bool remove(const KK& key)
			{
				zint index = keys_.firstindexof(key);
				if (index != -1)
				{
					keys_.removeat(index);
					List<VT, VK>* target = values_[index];
					values_.removeat(index);
					delete target;
					return true;
				}
				else
				{
					return false;
				}
			}

			bool remove(const KK& key, const VK& value)
			{
				zint index = keys_.indexof(key);
				if (index != -1)
				{
					List<VT, VK>* target = values_[index];
					target->remove(value);
					if (target->Count() == 0)
					{
						keys_.removeat(index);
						values_.removeat(index);
						delete target;
					}
					return true;
				}
				else return false;
			}

			bool clear()
			{
				for (zint i = 0; i < values_.size(); i++)
				{
					delete values_[i];
				}
				keys_.clear();
				values_.clear();
				return true;
			}
		};
	};
};
#endif